﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;


namespace OrderManager
{
    public partial class NewOrder : Form
    {
        bool modify;
        int orderCount;
        

        public NewOrder()
        {
            InitializeComponent();
            StreamReader OrderNumberReader;

            // Az elérhető ételek dobozának feltöltése a menü alapján
            for (int i = 0; i < Program.foodList.Count; ++i)
            {
                Menu.Items.Add(Program.foodList[i].Name);
            }

            // A rendelés azonosítójának legenerálása
            try
            {
                OrderNumberReader = File.OpenText("OrderCounter.txt");
                orderCount = int.Parse(OrderNumberReader.ReadLine());
                OrderNumberReader.Close();
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message);
                this.Close();
                return;
            }

            this.modify = false;            
            this.orderID.Text = CommonFunctions.To36Based(orderCount);
            ShowOrderSummary();


            return;
        }

        // Konstruktor, amit a ModifyOrder-ből hívunk, ez a kiválaszott, paraméterül kapott fájlnév alapján fogja betölteni
        // a rendelés adatait, és azokat betenni a megfelelő mezőkbe
        public NewOrder(string orderID)
        {
            InitializeComponent();
            this.Text = "Megrendelés módosítása";
            StreamReader order;

            // Az elérhető ételek dobozának feltöltése a menü alapján
            for (int i = 0; i < Program.foodList.Count; ++i)
            {
                Menu.Items.Add(Program.foodList[i].Name);
            }

            // A rendelés adatait tartalmazó fájl betöltése
            try
            {
                order = File.OpenText(orderID);
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message);
                this.Close();
                return;
            }

            // A rendelés mezőinek kitöltése a fájl alapján
            string tmp = order.ReadLine();
            this.nameBox.Text = order.ReadLine().Split(':')[1].Substring(1);
            this.addressBox.Text = order.ReadLine().Split(':')[1].Substring(1);
            tmp = order.ReadLine().Substring(1);
            this.phonePrefixBox.Text = tmp.Split('-')[1];
            this.phoneBox.Text = tmp.Split('-')[2];

            // Dátum
            tmp = order.ReadLine();
            tmp = tmp.Split(':')[1].TrimStart();
            this.dateBox.Value = DateTime.Parse(tmp);

            // Idő
            tmp = order.ReadLine();
            this.hourBox.Text = tmp.Split(':')[1].Substring(1);
            this.minBox.Text = tmp.Split(':')[2];

            // Idő hozzáadása a dátumhoz
            try
            {
                this.dateBox.Value = this.dateBox.Value.AddHours(int.Parse(this.hourBox.Text));
                this.dateBox.Value = this.dateBox.Value.AddMinutes(int.Parse(this.minBox.Text));
            }
            catch (Exception exc)
            {
                MessageBox.Show("A bemeneti fájl sérült vagy nem olvasható");
                order.Close();
                this.Close();

                return;
            }

            tmp = order.ReadLine();
            tmp = order.ReadLine();
            tmp = order.ReadLine();
            tmp = order.ReadLine();
            tmp = order.ReadLine();
            this.orderID.Text = tmp.Split(' ')[1];
            tmp = order.ReadLine();
            tmp = order.ReadLine();
            while (!order.EndOfStream)
            {
                this.OrderedItems.Items.Add(order.ReadLine());
            }
            order.Close();
            //--------------------------------------------------

            ShowOrderSummary();
            this.modify = true;
            
            return;
        }

        // Összegzi a megrendelésben szereplő ételek árait, megszámolja azokat, és beírja ezeket a megfelelő mezőkbe
        private void ShowOrderSummary()
        {
            int cost = 0;
            for (int i = 0; i < OrderedItems.Items.Count; ++i)
            {
                int a = CommonFunctions.FindItemByName(Program.foodList, OrderedItems.Items[i].ToString());
                cost += Program.foodList[a].Price;
            }
            this.numberOfItems.Text = OrderedItems.Items.Count.ToString();
            this.totalCost.Text = cost.ToString() + " Ft";
            return;
        }

        // A menün bepipált ételeket hozzáadja a megrendelt ételek listájához
        private void AddItemsToChart(object sender, EventArgs e)
        {
            for (int i = 0; i<Menu.CheckedItems.Count; ++i)
            {
                OrderedItems.Items.Add(Menu.CheckedItems[i]);
            }

            ShowOrderSummary();

            return;
        }

        // A kiválaszott ételek listáján szereplő bejelölt ételeket távolítja el
        private void RemoveItemsFromChart(object sender, EventArgs e)
        {
            int i = 0;

            while (i < OrderedItems.Items.Count)
            {
                if (OrderedItems.GetItemChecked(i)) OrderedItems.Items.RemoveAt(i);
                else ++i;
            }

            ShowOrderSummary();
            return;
        }

        // Az ablak alján lévő súgódobozba írja be a szövegeket, ha a felhasználó a kurzort az egyes vezérlők fölé viszi
        private void ShowHelp(object sender, EventArgs e)
        {
                 if (sender == this.Menu) this.HelpTextbox.Text = "Az elérhető ételek listája. Egy étel többszöri megrendeléséhez a hozzáadás gombot megfelelő darabszámszor kell megnyomni.";
            else if (sender == this.OrderedItems) this.HelpTextbox.Text = "A megrendelt ételek listája. Eltávolításhoz ki kell jelölni a nem kívánt elemeket, majd az eltávolítás gombra nyomni.";
            else if (sender == this.removeItemsBtn) this.HelpTextbox.Text = "A kijelölt elemek eltávolítása a megrendelési listáról.";
            else if (sender == this.addItemsBtn) this.HelpTextbox.Text = "Ételek felvétele a megrendelési listára. Egy elem többszöri hozzáadásához a gombot annyiszor kell megnyomni, ahányat a fogyasztó rendel.";
            else if (sender == this.nameBox) this.HelpTextbox.Text = "A megrendelő neve.";
            else if (sender == this.addressBox) this.HelpTextbox.Text = "A kiszállítási cím. Helyben fogyasztás esetén elhagyható.";
            else if (sender == this.phonePrefixBox) this.HelpTextbox.Text = "A megrendelő telefonszáma.";
            else if (sender == this.phoneBox) this.HelpTextbox.Text = "A megrendelő telefonszáma.";
            else if (sender == this.dateBox) this.HelpTextbox.Text = "A megrendelést melyik napon kell teljesíteni.";
            else if (sender == this.hourBox) this.HelpTextbox.Text = "A megrendelt ételeknek mikorra kell elkészülnie helyben fogyasztás esetén, illetve mikorra kell kiszállítani házhozszállítás esetén.";
            else if (sender == this.minBox) this.HelpTextbox.Text = "A megrendelt ételeknek mikorra kell elkészülnie helyben fogyasztás esetén, illetve mikorra kell kiszállítani házhozszállítás esetén.";
            else if (sender == this.withDelivery) this.HelpTextbox.Text = "Kiválasztható, hogy a fogyasztó házhozszállítást kér, vagy egy éttermünkben veszi át a megrendelést.";
            else if (sender == this.noDelivery) this.HelpTextbox.Text = "Kiválasztható, hogy a fogyasztó házhozszállítást kér, vagy egy éttermünkben veszi át a megrendelést.";
            else if (sender == this.numberOfItems) this.HelpTextbox.Text = "A megrendelt ételek jelenlegi száma.";
            else if (sender == this.totalCost) this.HelpTextbox.Text = "A megrendelés végösszege a jelenleg felvett ételek alapján.";
            else if (sender == this.orderID) this.HelpTextbox.Text = "A megrendelés azonosítója.";
            else if (sender == this.cancelBtn) this.HelpTextbox.Text = "A megrendelés elvetése, a változások mentése nélkül.";
            else if (sender == this.AddOrderBtn) this.HelpTextbox.Text = "A megrendelés jóváhagyása.";
        }

        // Ha a kurzor kimegy egy vezérlő területéről, a súgó ne mutasson semmit
        private void ClearHelpBox(object sender, EventArgs e)
        {
            this.HelpTextbox.Text = "";
        }
        
        // Az adatok bevitele közben ellenőrizteti azok helyességét
        private void LiveCheck(object sender, EventArgs e)
        {
                 if (sender == this.Menu) ValidateNumberOfOrders();
            else if (sender == this.nameBox) ValidateName();
            else if (sender == this.addressBox) ValidateAddress();
            else if (sender == this.phoneBox || sender == this.phonePrefixBox) ValidatePhoneNumber();
            else if (sender == this.dateBox || sender == this.hourBox || sender == this.minBox) ValidateDateTime();

            return;
        }

        // A megrendelés jóváhagyását végző függvény
        private void SaveOrder(object sender, EventArgs e)
        {
            if (!ValidateOrder())
            {
                MessageBox.Show("A pirossal megjelölt adatok érvénytelenek.");
                return;
            }

            // Összeállítjuk a megrendelési fájl tartalmát--------------------------------------------------------------------------
            StringBuilder orderData = new StringBuilder();
            orderData.AppendLine("========Megrendelés=========");
            orderData.AppendLine("Név: " + this.nameBox.Text.Trim());
            orderData.AppendLine("Cím: " + this.addressBox.Text.Trim());
            orderData.AppendLine("Telefonszám: 06-" + this.phonePrefixBox.Text + "-" + this.phoneBox.Text);
            orderData.AppendLine("Megrendelés dátuma: " + this.dateBox.Text);
            orderData.AppendLine("Megrendelés időpontja: " + this.hourBox.Text + ":" + this.minBox.Text);
            orderData.AppendLine("Fogyasztás módja: " + ((this.noDelivery.Checked) ? "Helyben" : "Házhozszállítással"));
            orderData.AppendLine("----------------------");
            orderData.AppendLine("Megrendelt ételek száma: " + this.numberOfItems.Text);
            orderData.AppendLine("Végösszeg: " + this.totalCost.Text);
            orderData.AppendLine("Azonosító: " + this.orderID.Text);
            orderData.AppendLine("----------------------");
            orderData.AppendLine("Megrendelések:");
            for (int i = 0; i < this.OrderedItems.Items.Count; ++i)
            {
                orderData.AppendLine(this.OrderedItems.Items[i].ToString());
            }
            // -----------------------------------------------------------------------------------

            // Beleírjuk a fájlba a megrendelés tartalmát
            StreamWriter output;
            try
            {
                if (!modify)
                {
                    if (!Directory.Exists("Orders"))
                        Directory.CreateDirectory("Orders");
                    output = File.CreateText("Orders\\" + CommonFunctions.To36Based(orderCount) + ".txt");
                }
                else
                {
                    if (!Directory.Exists("Orders"))
                        Directory.CreateDirectory("Orders");
                    output = File.CreateText("Orders\\" + this.orderID.Text + ".txt");
                }


                output.Write(orderData);
                output.Flush();
                output.Close();
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message);
                return;
            }
            // ---------------------------------------------------------------------------------
            




            if (!modify)
            {
                StreamWriter OrderIDWriter;
                StreamWriter OrderNumberWriter;

                // A létező rendeléseket számontartó fájlba beleírjuk ennek a megrendelésnek az azonosítóját "36-os számrendszerbeli" alakban
                // TODO:
                // Ha a második dob csak kivételt, és az első már megváltozott, szétcsúsznak a dolgok. Ezt kijavítani helyreállítók stb használatával
                try
                {
                    OrderIDWriter = File.AppendText("Orders.txt");                    
                    OrderIDWriter.WriteLine(CommonFunctions.To36Based(orderCount));
                    OrderIDWriter.Flush();
                    OrderIDWriter.Close();

                    ++orderCount;

                    // Fájlba kiírjuk a következő rendelés azonosítóját decimálisan
                    OrderNumberWriter = File.CreateText("OrderCounter.txt");
                    OrderNumberWriter.WriteLine(orderCount);
                    OrderNumberWriter.Flush();
                    OrderNumberWriter.Close();
                }
                catch (Exception exc)
                {
                    MessageBox.Show(exc.Message);
                    return;
                }
            }

            

            MessageBox.Show("A megrendelés elmentve.");

            this.Close();
            return;
        }

        //A rendelések számának ellenőrzése
        private bool ValidateNumberOfOrders()
        {
            this.OrderedItems.BackColor = Color.FromArgb(255, 255, 255);

            if (this.OrderedItems.Items.Count <= 0)
            {
                this.OrderedItems.BackColor = Color.FromArgb(255, 128, 128);
                return false;
            }
            return true;
        }
        
        //A név ellenőrzése
        private bool ValidateName()
        {
            this.nameBox.BackColor = Color.FromArgb(255, 255, 255);

            if (this.nameBox.Text.Trim().Length < 5 || !this.nameBox.Text.Trim().Contains(' '))
            {
                this.nameBox.BackColor = Color.FromArgb(255, 128, 128);
                return false;
            }
            return true;
        }

        //A cím ellenőrzése
        private bool ValidateAddress()
        {
            this.addressBox.BackColor = Color.FromArgb(255, 255, 255);

            if (this.withDelivery.Checked && (this.addressBox.Text.Trim().Length < 5 || !this.addressBox.Text.Trim().Contains(' ')))
            {
                this.addressBox.BackColor = Color.FromArgb(255, 128, 128);
                return false;
            }
            return true;
        }

        //A telefonszám ellenőrzése
        private bool ValidatePhoneNumber()
        {
            this.phoneBox.Text = this.phoneBox.Text.Trim();
            this.phonePrefixBox.Text = this.phonePrefixBox.Text.Trim();
            this.phoneBox.BackColor = this.phonePrefixBox.BackColor = Color.FromArgb(255, 255, 255);

            //Ha nincs körzethívószám, akkor automatikusan állítsa azt 1-re
            if (this.phonePrefixBox.Text == "") this.phonePrefixBox.Text = "1";

            int n;
            // A követkető elágazás feltételének végén azért teszteljük, hogy n < 10000, mert ezzel egyrészt ellenőrizhető az is,
            // hogy a telefonszám pozitív szám, másrészt hogy legalább 5 karakter hosszú, amit elvárunk
            //
            // Eml.: Az int.TryParse(...) false-val tér vissza, ha az értelmezendő, ténylegesen csak számokból álló sorozat 0-val kezdődik
            if ((int.TryParse(this.phonePrefixBox.Text,out n) && n>0) && (int.TryParse(this.phoneBox.Text, out n) && n < 10000))
            {
                this.phoneBox.BackColor = this.phonePrefixBox.BackColor = Color.FromArgb(255, 128, 128);
                return false;
            }
            return true;
        }

        private bool ValidateDateTime()
        {
            this.hourBox.Text = this.hourBox.Text.Trim();
            this.minBox.Text = this.minBox.Text.Trim();

            ///----------
            ///TODO
            ///----------
            ///A dátummal baj van, ha a mindenkori mai napot választom ki, nem hitelesítődik (segítség: a kimeneti fájlban csak az év-hó-nap jelenik meg, az idő nem, talán formátummódosítás kell.
            //A dátum hitelesítése
            DateTime date = this.dateBox.Value.Date;
            int hourVal = 0;
            int minuteVal = 0;
            bool valid = true;


            this.hourBox.BackColor = this.minBox.BackColor = Color.FromArgb(255, 255, 255);

            if (!int.TryParse(this.hourBox.Text, out hourVal) || hourVal < 0 || hourVal > 23)
            {
                valid = false;
                this.hourBox.BackColor = Color.FromArgb(255, 128, 128);
            }
            if (!int.TryParse(this.minBox.Text, out minuteVal) || minuteVal < 0 || minuteVal > 59)
            {
                valid = false;
                this.minBox.BackColor = Color.FromArgb(255, 128, 128);
            }
            if (!valid)
            {
                return false;
            }


            date = date.AddHours( hourVal );
            date = date.AddMinutes( minuteVal );
            if (date < DateTime.Now)
            {
                this.dateBox.CalendarForeColor = Color.FromArgb(255, 128, 128);
                hourBox.BackColor = Color.FromArgb(255, 128, 128);
                minBox.BackColor = Color.FromArgb(255, 128, 128);
                return false;
            }
            return true;
        }

        private bool ValidateOrder()
        {
            this.OrderedItems.BackColor = this.nameBox.BackColor = this.addressBox.BackColor = this.phoneBox.BackColor = this.phonePrefixBox.BackColor = this.hourBox.BackColor = this.minBox.BackColor = this.dateBox.CalendarForeColor = Color.FromArgb(255,255,255);
            
            bool numberOfOrdersValidated,nameValidated,addressValidated,phoneValidated,dateValidated;
            
            // Az ellenőrzéseket azért nem rögtön a return-ban végeztetjüók el, mert ha van egy hibás bemenet, amire nyilván az eredmény false, akkor a többi nem fog ellenőrződni,
            // de kellene, hogy egy jóváhagyáskor az összes hibás mező be legyen jelölve pirossal.
            numberOfOrdersValidated = ValidateNumberOfOrders();
            nameValidated = ValidateName();
            addressValidated = ValidateAddress();
            phoneValidated = ValidatePhoneNumber();
            dateValidated = ValidateDateTime();

            return numberOfOrdersValidated && nameValidated && addressValidated && phoneValidated && dateValidated;
        }

    }
}
